/*
 * CircleDrawer.java
 *
 * Created on November 4, 2006, 10:44 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package edu.umn.cs5115.scheduler.circle;

import edu.umn.cs5115.scheduler.framework.DocumentController;
import edu.umn.cs5115.scheduler.framework.KeyValueCoding;
import edu.umn.cs5115.scheduler.framework.KeyValueObserver;

import java.util.Set;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;

/**
 *
 * @author grant
 */
public class CircleDrawer extends Canvas implements KeyValueObserver, PaintListener, MouseListener
{
    private Circle circle;
    private Color backgroundColor;
    private Color circleColor;
    private boolean mouseIsDown;
    /** Creates a new instance of CircleDrawer 
     * @param circle The Circle to draw
     */
    public CircleDrawer(Composite parent, Circle circle)
    {
        super(parent, SWT.NO_BACKGROUND | SWT.DOUBLE_BUFFERED);
        this.circle = circle;
        // register to receive notifications of changes that will change
        // how the circle appears.
        circle.addListener(this, Circle.COLOR_KEY);
        circle.addListener(this, Circle.RADIUS_KEY);
        circle.addListener(this, Circle.CENTER_KEY);
        backgroundColor = new Color(DocumentController.getSharedDocumentController().getDisplay(), 255, 255, 255);
        makeCircleColor();
        addPaintListener(this);
        addMouseListener(this);
    }

    public void dispose()
    {
        backgroundColor.dispose();
        circleColor.dispose();
        circle.removeListener(this);
        super.dispose();
    }
    
    public void valueChanged(KeyValueCoding object, String key)
    {
        if (key == Circle.COLOR_KEY)
            makeCircleColor();
        redraw();
    }

    public void paintControl(PaintEvent e)
    {
        GC g = e.gc;
        g.setBackground(backgroundColor);
        g.fillRectangle(e.x,e.y,e.width,e.height);
        g.setBackground(circleColor);
        int radius = (int)circle.getRadius();
        g.fillOval(circle.getCenterX()-radius, circle.getCenterY()-radius, 2 * radius, 2 * radius);
    }

    public void mouseDoubleClick(MouseEvent e)
    {
    }

    public void mouseDown(MouseEvent e)
    {
        circle.setCenterX(e.x);
        circle.setCenterY(e.y);
        // disable undo registration for the duration of the drag, just to
        // prevent there from being a TON of nested undos that aren't necessary.
        circle.getDocument().getUndoManager().disableUndoRegistration();
        // hijack the event loop to track the mouse.
        mouseIsDown = true;
        MouseMoveListener tracker = new MouseMoveListener()
        {
            public void mouseMove(MouseEvent e)
            {
                circle.setCenterX(e.x);
                circle.setCenterY(e.y);
            }
        };
        addMouseMoveListener(tracker);
        Display display = DocumentController.getSharedDocumentController().getDisplay();
        while(mouseIsDown)
        {
            if(!display.readAndDispatch())
                display.sleep();
        }
        removeMouseMoveListener(tracker);
    }

    public void mouseUp(MouseEvent e)
    {
        mouseIsDown = false;
        // re-enable undo registration
        circle.getDocument().getUndoManager().enableUndoRegistration();
        circle.setCenterX(e.x);
        circle.setCenterY(e.y);
        circle.getDocument().getUndoManager().setActionName("Move Circle");
    }

    private void makeCircleColor()
    {
        if (circleColor != null)
            circleColor.dispose();
        circleColor = new Color(DocumentController.getSharedDocumentController().getDisplay(),
                circle.getRed(), circle.getGreen(), circle.getBlue());
    }

    /** required by interface; ignored. */
    public void valueChanged(KeyValueCoding object, String key, KeyValueObserver.SetMutationType mutation, Set modifyingSet){}
}
